home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / gs24src.zip / IUTILASM.ASM < prev    next >
Assembly Source File  |  1992-02-23  |  8KB  |  393 lines

  1. ;    Copyright (C) 1989, 1992 Aladdin Enterprises.  All rights reserved.
  2. ;    Distributed by Free Software Foundation, Inc.
  3. ;
  4. ; This file is part of Ghostscript.
  5. ;
  6. ; Ghostscript is distributed in the hope that it will be useful, but
  7. ; WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. ; to anyone for the consequences of using it or for whether it serves any
  9. ; particular purpose or works at all, unless he says so in writing.  Refer
  10. ; to the Ghostscript General Public License for full details.
  11. ;
  12. ; Everyone is granted permission to copy, modify and redistribute
  13. ; Ghostscript, but only under the conditions described in the Ghostscript
  14. ; General Public License.  A copy of this license is supposed to have been
  15. ; given to you along with Ghostscript so you can know your rights and
  16. ; responsibilities.  It should be in a file named COPYING.  Among other
  17. ; things, the copyright notice and this notice must be preserved on all
  18. ; copies.
  19.  
  20. ; iutilasm.asm
  21. ; Assembly code for Ghostscript interpreter on MS-DOS systems
  22.  
  23.     ifdef    FOR80386
  24.  
  25.     .286c
  26.  
  27.     endif
  28.  
  29. utilasm_TEXT    SEGMENT    WORD PUBLIC 'CODE'
  30.     ASSUME    CS:utilasm_TEXT
  31.  
  32.  
  33.     ifdef    FOR80386
  34.  
  35. ; Macro for 32-bit operand prefix.
  36. OP32    macro
  37.     db    66h
  38.     endm
  39.  
  40.     endif                    ; FOR80386
  41.  
  42.  
  43.     ifdef    FOR80386
  44.  
  45. ; Replace the multiply and divide routines in the Turbo C library
  46. ; if we are running on an 80386.
  47.  
  48. ; Macro to swap the halves of a 32-bit register.
  49. ; Unfortunately, masm won't allow a shift instruction with a count of 16,
  50. ; so we have to code it in hex.
  51. swap    macro    regno
  52.       OP32
  53.     db    0c1h,0c0h+regno,16        ; rol regno,16
  54.     endm
  55. regax    equ    0
  56. regcx    equ    1
  57. regdx    equ    2
  58. regbx    equ    3
  59.  
  60. ; Multiply (dx,ax) by (cx,bx) to (dx,ax).
  61.     PUBLIC    LXMUL@
  62.     PUBLIC    F_LXMUL@
  63. F_LXMUL@ proc    far
  64. LXMUL@    proc    far
  65.     swap    regdx
  66.     mov    dx,ax
  67.     swap    regcx
  68.     mov    cx,bx
  69.       OP32
  70.     db    0fh,0afh,0d1h            ; imul dx,cx
  71.       OP32
  72.     mov    ax,dx
  73.     swap    regdx
  74.     ret
  75. LXMUL@    endp
  76. F_LXMUL@ endp
  77.  
  78. ; Divide two stack operands, leave the result in (dx,ax).
  79. setup32    macro
  80.     mov    bx,sp
  81.       OP32
  82.     mov    ax,ss:[bx+4]            ; dividend
  83.     endm
  84.     PUBLIC    LDIV@, LUDIV@, LMOD@, LUMOD@
  85.     PUBLIC    F_LDIV@, F_LUDIV@, F_LMOD@, F_LUMOD@
  86. F_LDIV@    proc    far
  87. LDIV@    proc    far
  88.     setup32
  89.       OP32
  90.     cwd
  91.       OP32
  92.     idiv    word ptr ss:[bx+8]        ; divisor
  93.       OP32
  94.     mov    dx,ax
  95.     swap    regdx
  96.     ret    8
  97. LDIV@    endp
  98. F_LDIV@    endp
  99. F_LUDIV@ proc    far
  100. LUDIV@    proc    far
  101.     setup32
  102.       OP32
  103.     xor    dx,dx
  104.       OP32
  105.     div    word ptr ss:[bx+8]        ; divisor
  106.       OP32
  107.     mov    dx,ax
  108.     swap    regdx
  109.     ret    8
  110. LUDIV@    endp
  111. F_LUDIV@ endp
  112. F_LMOD@    proc    far
  113. LMOD@    proc    far
  114.     setup32
  115.       OP32
  116.     cwd
  117.       OP32
  118.     idiv    word ptr ss:[bx+8]        ; divisor
  119.       OP32
  120.     mov    ax,dx
  121.     swap    regdx
  122.     ret    8
  123. LMOD@    endp
  124. F_LMOD@    endp
  125. F_LUMOD@ proc    far
  126. LUMOD@    proc    far
  127.     setup32
  128.       OP32
  129.     xor    dx,dx
  130.       OP32
  131.     div    word ptr ss:[bx+8]        ; divisor
  132.       OP32
  133.     mov    ax,dx
  134.     swap    regdx
  135.     ret    8
  136. LUMOD@    endp
  137. F_LUMOD@ endp
  138.  
  139.     else                    ; !FOR80386
  140.  
  141. ; Replace the unsigned divide routines in the Turbo C library,
  142. ; which do the division one bit at a time (!).  (We should replace
  143. ; the signed divide routines as well, but it's too much work.)
  144.  
  145.     PUBLIC    LUDIV@, LUMOD@
  146.     PUBLIC    F_LUDIV@, F_LUMOD@
  147.  
  148. ; Divide two unsigned longs on the stack.
  149. ; Leave either the quotient or the remainder in (dx,ax).
  150.  
  151. ; We use an offset in bx distinguish div from mod.
  152. F_LUMOD@ proc    far
  153. LUMOD@    proc    far
  154.     mov    bx,2
  155.     jmp    udiv
  156. LUMOD@    endp
  157. F_LUMOD@ endp
  158. F_LUDIV@ proc    far
  159. LUDIV@    proc    far
  160.     xor    bx,bx
  161. udiv:    push    bp
  162.     push    bx                ; 0 = div, 2 = mod
  163.     mov    bp,sp
  164. nlo    equ    8
  165. nhi    equ    10
  166. dlo    equ    12
  167. dhi    equ    14
  168.     mov    ax,[bp+nlo]
  169.     mov    dx,[bp+nhi]
  170.     mov    bx,[bp+dlo]
  171.     mov    cx,[bp+dhi]
  172. ; Now we are dividing dx:ax by cx:bx.
  173. ; Check to see whether this is really a 32/16 division.
  174.     or    cx,cx
  175.     jnz    div2
  176. ; 32/16, check for 16- vs. 32-bit quotient
  177.     cmp    dx,bx
  178.     jae    div1
  179. ; 32/16 with 16-bit quotient, just do it.
  180.     div    bx                ; ax = quo, dx = rem
  181.     pop    bx
  182.     pop    bp
  183.     jmp    cs:xx1[bx]
  184.     even
  185. xx1    dw    divx1
  186.     dw    modx1
  187. divx1:    xor    dx,dx
  188.     ret    8
  189. modx1:    mov    ax,dx
  190.     xor    dx,dx
  191.     ret    8
  192. ; 32/16 with 32-bit quotient, do in 2 parts.
  193. div1:    mov    cx,ax                ; save lo num
  194.     mov    ax,dx
  195.     xor    dx,dx
  196.     div    bx                ; ax = hi quo
  197.     xchg    cx,ax                ; save hi quo, get lo num
  198.     div    bx                ; ax = lo quo, dx = rem
  199.     pop    bx
  200.     pop    bp
  201.     jmp    cs:xx1a[bx]
  202.     even
  203. xx1a    dw    offset divx1a
  204.     dw    offset modx1
  205. divx1a:    mov    dx,cx                ; hi quo
  206.     ret    8
  207. ; This is really a 32/32 bit division.
  208. ; (Note that the quotient cannot exceed 16 bits.)
  209. ; The following algorithm is taken from pp. 235-240 of Knuth, vol. 2
  210. ; (first edition).
  211. ; Start by normalizing the numerator and denominator.
  212. div2:    or    ch,ch
  213.     jz    div21                ; ch == 0, but cl != 0
  214. ; Do 8 steps all at once.
  215.     mov    bl,bh
  216.     mov    bh,cl
  217.     mov    cl,ch
  218.     xor    ch,ch
  219.     mov    al,ah
  220.     mov    ah,dl
  221.     mov    dl,dh
  222.     xor    dh,dh
  223.     rol    bx,1                ; cancel following rcr
  224. div2a:    rcr    bx,1                ; finish previous shift
  225. div21:    shr    dx,1
  226.     rcr    ax,1
  227.     shr    cx,1
  228.     jnz    div2a
  229.     rcr    bx,1
  230. ; Now we can do a 32/16 divide.
  231. div2x:    div    bx                ; ax = quo, dx = rem
  232. ; Multiply by the denominator, and correct the result.
  233.     mov    cx,ax                ; save quotient
  234.     mul    word ptr [bp+dhi]
  235.     mov    bx,ax                ; save lo part of hi product
  236.     mov    ax,cx
  237.     mul    word ptr [bp+dlo]
  238.     add    dx,bx
  239. ; Now cx = trial quotient, (dx,ax) = cx * denominator.
  240.     not    dx
  241.     neg    ax
  242.     cmc
  243.     adc    dx,0                ; double-precision neg
  244.     jc    divz                ; zero quotient
  245.                         ; requires special handling
  246.     add    ax,[bp+nlo]
  247.     adc    dx,[bp+nhi]
  248.     jc    divx
  249. ; Quotient is too large, adjust it.
  250. div3:    dec    cx
  251.     add    ax,[bp+dlo]
  252.     adc    dx,[bp+dhi]
  253.     jnc    div3
  254. ; All done.  (dx,ax) = remainder, cx = lo quotient.
  255. divx:    pop    bx
  256.     pop    bp
  257.     jmp    cs:xx3[bx]
  258.     even
  259. xx3    dw    offset divx3
  260.     dw    offset modx3
  261. divx3:    mov    ax,cx
  262.     xor    dx,dx
  263. modx3:    ret    8
  264. ; Handle zero quotient specially.
  265. divz:    pop    bx
  266.     jmp    cs:xxz[bx]
  267.     even
  268. xxz    dw    offset divxz
  269.     dw    offset modxz
  270. divxz:    pop    bp
  271.     ret    8
  272. modxz:    mov    ax,[bp+nlo-2]            ; adjust for popf
  273.     mov    dx,[bp+nhi-2]
  274.     pop    bp
  275.     ret    8
  276. LUDIV@    endp
  277. F_LUDIV@ endp
  278.  
  279.     endif                    ; FOR80386
  280.  
  281. ; Swap even and odd bytes from src to dest.
  282. ; See gsmisc.c for the C definition.
  283.     PUBLIC    _memswab
  284. _memswab proc    far
  285.     mov    bx,sp
  286.     push    ds
  287.     push    si
  288.     mov    dx,ss:[bx+12]            ; count
  289.     shr    dx,1
  290.     shr    dx,1
  291.     les    si,ss:[bx+4]            ; src
  292.     lds    bx,ss:[bx+8]            ; dest
  293.     jnc    sw3
  294.     add    si,2
  295.     sub    bx,2
  296.     jmp    sw2
  297. sw1:    mov    ax,es:[si]
  298.     add    si,4
  299.     xchg    ah,al
  300.     mov    [bx],ax
  301. sw2:    mov    ax,es:[si-2]
  302.     add    bx,4
  303.     xchg    ah,al
  304.     mov    [bx-2],ax
  305. sw3:    dec    dx
  306.     jge    sw1
  307.     pop    si
  308.     pop    ds
  309.     ret
  310. _memswab ENDP
  311.  
  312. ; Transpose an 8x8 bit matrix.  See gsmisc.c for the algorithm in C.
  313.     PUBLIC    _memflip8x8
  314. _memflip8x8 proc far
  315.     push    ds
  316.     push    si
  317.     push    di
  318.         ; After pushing, the offsets of the parameters are:
  319.         ; byte *inp=10, int line_size=14, byte *outp=16, int dist=20.
  320.     mov    si,sp
  321.     mov    di,ss:[si+14]            ; line_size
  322.     lds    si,ss:[si+10]            ; inp
  323.         ; We assign variables to registers as follows:
  324.         ; ax = AE, bx = BF, cx (or di) = CG, dx = DH.
  325.         ; Load the input data.  Initially we assign
  326.         ; ax = AB, bx = EF, cx (or di) = CD, dx = GH.
  327.     mov    ah,[si]
  328. iload    macro    reg
  329.     add    si,di
  330.     mov    reg,[si]
  331.     endm
  332.     iload    al
  333.     iload    ch
  334.     iload    cl
  335.     iload    bh
  336.     iload    bl
  337.     iload    dh
  338.     iload    dl
  339.         ; Transposition macro, see C code for explanation.
  340. trans    macro    reg1,reg2,shift,mask
  341.     mov    si,reg1
  342.     shr    si,shift
  343.     xor    si,reg2
  344.     and    si,mask
  345.     xor    reg2,si
  346.     shl    si,shift
  347.     xor    reg1,si
  348.     endm
  349.         ; Do 4x4 transpositions
  350.     mov    di,cx            ; we need cl for the shift count
  351.     mov    cl,4
  352.     trans    bx,ax,cl,0f0fh
  353.     trans    dx,di,cl,0f0fh
  354.         ; Swap B/E, D/G
  355.     xchg    al,bh
  356.     mov    cx,di
  357.     xchg    cl,dh
  358.         ; Do 2x2 transpositions
  359.     mov    di,cx                ; need cl again
  360.     mov    cl,2
  361.     trans    di,ax,cl,3333h
  362.     trans    dx,bx,cl,3333h
  363.     mov    cx,di                ; done shifting >1
  364.         ; Do 1x1 transpositions
  365.     trans    bx,ax,1,5555h
  366.     trans    dx,cx,1,5555h
  367.         ; Store result
  368.     mov    si,sp
  369.     mov    di,ss:[si+20]            ; dist
  370.     lds    si,ss:[si+16]            ; outp
  371.     mov    [si],ah
  372. istore    macro    reg
  373.     add    si,di
  374.     mov    [si],reg
  375.     endm
  376.     istore    bh
  377.     istore    ch
  378.     istore    dh
  379.     istore    al
  380.     istore    bl
  381.     istore    cl
  382.     istore    dl
  383.         ; All done
  384.     pop    di
  385.     pop    si
  386.     pop    ds
  387.     ret
  388. _memflip8x8 ENDP
  389.  
  390.  
  391. utilasm_TEXT ENDS
  392.     END
  393.